<script setup lang="ts">
/**
 * @name ApplicationModelConfigs
 * @description 应用模型配置
 */
import type { Action } from 'element-plus'
import ResponsiveModels from '../IndicatorTopologicalGraph/components/ResponsiveModels/ResponsiveModels.vue'
import IndicatorsBox from './components/IndicatorsBox/IndicatorsBox.vue'
import { useModelIndicators } from './ApplicationModelConfigs'
import { useModelLists } from '@/views/ApplicationModels/ApplicationModels'
import type {
  ApplicationModel,
  ApplicationModelIndicator,
} from '@/types/modules/application-models'
import type { Point } from '@/components/ReadonlyPointTree/ReadonlyPointTree'

import {
  deleteModelIndicator,
  saveModelIndicator,
} from '@/api/modules/applicationModel'

type NodeLists = (Point & {
  data: ApplicationModel['data']
})[]

const {
  lists: modelLists,
  children,
  loading,
  getLists,
  getChildrenById,

  toApplicationModelConfigs,
  toApplicationModels,
} = useModelLists()
const nodeLists = computed<NodeLists>(() => {
  const recursive = (
    array: ApplicationModel[],
  ): NodeLists => {
    return array.reduce((acc, cur) => {
      acc.push({
        id: cur.id,
        parentId: cur.parentId,
        pointName: cur.name,
        data: cur.data,
        children:
          cur.children && cur.children.length > 0
            ? recursive(cur.children)
            : [],
      })
      return acc
    }, [] as NodeLists)
  }
  return recursive(unref(children))
})
const [modelId, setModelId] = useState(0)
const [point, setPoint] = useState<Point | null>(null)
const [modelPoint, setModelPoint] = useState<Point | null>(
  null,
)
const includeSub = ref(false)

const {
  indicatorLoading,
  indicators,
  getIndicatorsOfPoint,
  modelIndicators,
  setModelIndicators,
  modelIndicatorLoading,
  getIndicatorsOfModel,
  confirmDel,
} = useModelIndicators()

const selectedIndicatorsKeyword = ref('')
const unselectedIndicatorsKeyword = ref('')
const selectedIndicators = computed(() => {
  return unref(modelIndicators)
})
const selectedIndicatorsFiltered = computed(() => {
  const keyword = unref(selectedIndicatorsKeyword)
  return unref(selectedIndicators).filter(v =>
    v.indicatorName.includes(keyword),
  )
})
const unselectedIndicators = computed(() => {
  const modelId = unref(modelPoint)?.id
  const d = unref(includeSub)
    ? unref(selectedIndicators).filter(
      v => v.applicationModelId === modelId,
    )
    : unref(selectedIndicators)
  return unref(indicators).filter(
    v => !d.some(vv => vv.indicatorId === v.indicatorId),
  )
})
const unselectedIndicatorsFiltered = computed(() => {
  const keyword = unref(unselectedIndicatorsKeyword)
  return unref(unselectedIndicators).filter(v =>
    v.indicatorName.includes(keyword),
  )
})
const selectedIndicatorsChecked = ref<
  ApplicationModelIndicator[]
>([])
const unselectedIndicatorsChecked = ref<
  ApplicationModelIndicator[]
>([])

watchEffect(() => {
  const mid = unref(modelId)
  if (mid > 0) {
    getChildrenById(mid)
    // 切换模型时置空选中的点
    setPoint(null)
  }
})

watchEffect(() => {
  const mp = unref(modelPoint)
  if (mp) {
    getIndicatorsOfModel(mp.id, includeSub.value)
  }
})
watchEffect(() => {
  const p = unref(point)
  if (p) {
    getIndicatorsOfPoint(p.id)
  }
})

function handleClickModel(o: Point) {
  setModelPoint(o)
}
function handleClickPoint(o: Point) {
  setPoint(o)
}

async function toLeft() {
  const d = unref(selectedIndicatorsChecked)
  if (d.length > 0) {
    const action: Action = await confirmDel().catch(e => e)
    if (action !== 'confirm')
      return
    // 删除选中的指标（更新模型配置）
    try {
      await deleteModelIndicator(
        d.map(o => ({
          modelId: o.applicationModelId!,
          modelIndicatorId: o.indicatorId,
        })),
      )
      setModelIndicators(
        unref(modelIndicators).filter(
          i => !d.some(v => v.id === i.id),
        ),
      )
    }
    catch (e) {}
  }
}
async function toRight() {
  const d = unref(unselectedIndicatorsChecked)
  if (d.length > 0) {
    // 添加选中的指标（更新模型配置）
    try {
      const modelId = unref(modelPoint)?.id
      if (!modelId) {
        ElMessage.warning('请先选择模型')
        return
      }
      await saveModelIndicator(
        d.map(o => ({
          applicationModelId: modelId,
          indicatorId: o.indicatorId,
        })),
      )
      // setModelIndicators(unref(modelIndicators).concat(d));
      // 刷新模型指标
      const old = { ...unref(modelPoint) }
      setModelPoint(null)
      setTimeout(() => {
        setModelPoint(old as Point)
      }, 20)
    }
    catch (e) {}
  }
}

onMounted(async () => {
  await getLists()
  const mid = unref(modelLists)[0]?.id
  if (mid) {
    setModelId(mid)
  }
})
</script>

<template>
  <div class="padding-sm flex container">
    <div
      class="flex-direction tree-container flex flex-shrink-0"
    >
      <div class="width-fill relative flex-shrink-0">
        <h3 class="!margin-0">
          应用模型
        </h3>
        <div class="special-select">
          <ElSelect
            v-model="modelId"
            class="free"
            placeholder="请选择应用模型"
          >
            <ElOption
              label="请选择"
              :value="0"
              disabled
            />
            <ElOption
              v-for="item in modelLists"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </ElSelect>
          <ElCheckbox
            v-model="includeSub"
            label="包含下级"
          />
          <div class="flex flex-col">
            <ElLink
              class="margin-left-xs flex-shrink-0"
              type="primary"
              @click="toApplicationModels"
            >
              模型管理
            </ElLink>
            <ElLink
              class="margin-left-xs flex-shrink-0"
              type="primary"
              @click="toApplicationModelConfigs"
            >
              模型配置
            </ElLink>
          </div>
        </div>
        <div class="responsive">
          <ResponsiveModels
            v-model:model-id="modelId"
            v-model:include-sub="includeSub"
            :show-include-sub-checkbox="true"
            :data="modelLists"
          />
        </div>
      </div>
      <div
        v-loading="loading"
        element-loading-custom-class="global-loading"
        class="margin-top-sm flex-fillRemaining roll points-box"
      >
        <ReadonlyPointTree
          :show-title="false"
          external
          :points="nodeLists"
          @click-node="handleClickModel"
        />
      </div>
    </div>
    <div
      class="flex-direction tree-container margin-left-sm flex flex-shrink-0"
      style="flex-basis: 300px;"
    >
      <div class="align-center width-fill relative flex">
        <h3 class="!margin-0 flex-shrink-0">
          用能单元（点位）
        </h3>
      </div>
      <div
        class="margin-top-sm flex-fillRemaining points-box roll"
      >
        <ReadonlyPointTree
          :show-title="false"
          @click-node="handleClickPoint"
        />
      </div>
    </div>
    <div
      class="margin-left-sm flex-fillRemaining flex-direction roll flex justify-between"
    >
      <div class="flex-direction configs-box flex">
        <div class="align-center width-fill relative flex">
          <h3 class="!margin-0 flex-shrink-0">
            可配置的指标
          </h3>
        </div>
        <div
          class="margin-top-sm flex-fillRemaining flex-direction roll flex border rounded-sm"
        >
          <div class="indicator-filter flex-shrink-0">
            <ElInput
              v-model="unselectedIndicatorsKeyword"
              placeholder="关键字"
              class="free"
              clearable
            />
          </div>
          <div
            class="flex-fillRemaining roll indicator-wrapper"
          >
            <IndicatorsBox
              v-model="unselectedIndicatorsChecked"
              :loading="indicatorLoading"
              :data="unselectedIndicatorsFiltered"
            />
          </div>
        </div>
      </div>
      <div
        class="align-center margin-top-sm margin-bottom-sm flex flex-shrink-0 justify-center"
      >
        <ElTooltip content="添加配置" placement="top">
          <ElButton type="primary" @click="toRight">
            添加
          </ElButton>
        </ElTooltip>
        <ElTooltip content="移除配置" placement="top">
          <ElButton type="danger" @click="toLeft">
            删除
          </ElButton>
        </ElTooltip>
      </div>
      <div class="flex-direction configs-box flex">
        <div class="align-center width-fill relative flex">
          <h3 class="!margin-0 flex-shrink-0">
            已配置的指标
          </h3>
        </div>
        <div
          class="margin-top-sm flex-fillRemaining flex-direction roll flex border rounded-sm"
        >
          <div class="indicator-filter flex-shrink-0">
            <ElInput
              v-model="selectedIndicatorsKeyword"
              placeholder="关键字"
              class="free"
              clearable
            />
          </div>
          <div
            class="flex-fillRemaining indicator-wrapper roll"
          >
            <IndicatorsBox
              v-model="selectedIndicatorsChecked"
              :loading="modelIndicatorLoading"
              :data="selectedIndicatorsFiltered"
            />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.roll {
  @include roll();
}
.tree-container {
  flex-basis: 22%;
  transition: all 0.3s;
  @media screen and (max-width: 1800px) {
    flex-basis: 30%;
  }
}
.configs-box {
  flex: 0 0 calc((100% - 80px) / 2);
  overflow: hidden;
}
.responsive,
.special-select {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  width: calc(100% - 90px);
  :deep(.el-input) {
    min-width: auto !important;
  }
  :deep(.el-select) {
    flex: 1;
  }
  :deep(.el-checkbox) {
    margin-left: 10px;
  }
}
.responsive {
  display: none;
  :deep(.el-dropdown) {
    outline: none !important;
  }
  @media screen and (max-width: 1400px) {
    display: block;
    width: auto;
    outline: none;
  }
}
.special-select {
  @media screen and (max-width: 1400px) {
    display: none;
  }
}
.points-box {
  --container-left-width: 100%;
}
.indicator-filter {
  padding: var(--layout-gap-sm, 16px);
}
.indicator-wrapper {
  padding-left: var(--layout-gap-sm, 16px);
  padding-right: var(--layout-gap-sm, 16px);
  :deep(.el-table__inner-wrapper::before) {
    display: none;
  }
}
</style>
